﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace PACKETPARSERMAX20.CORE
{
    public class ReaderSniffitzSQLiteOLD : ReaderBase
    {


        private string name = "";
        private string fileName = "";
        private System.Data.SQLite.SQLiteConnection con;
        private System.Data.SQLite.SQLiteDataReader reader;
        private int currentIndex = 0;
        private int maxProcessCount = 300;
        private int total = -1;
        private string accountName = null;
        private int clientBuild = 0;

        public override int TotalStored
        {
            get
            {
                return total;
            }
        }

        public override int Total
        {
            get
            {
                if (total == -1)
                {
                    total = GetTotal();
                }
                return total;
            }
        }

        public override string Name
        {
            get
            {
                return name;
            }
        }

        public override int CurrentIndex
        {
            get
            {
                return currentIndex;
            }

            set
            {
                currentIndex = value;
            }
        }

        public override int MaxProcessCount
        {
            get
            {
                return maxProcessCount;
            }

            set
            {
                maxProcessCount = value;
            }
        }

        public override int ClientBuild
        {
            get
            {
                return clientBuild;
            }
        }

        public override string ClientBuildName
        {
            get
            {
                return ClientVersion.clientVersionList[clientBuild];
            }
        }

        public override string AccountName
        {
            get
            {
                return accountName;
            }
        }

        public ReaderSniffitzSQLiteOLD(string pFileName)
        {
            fileName = pFileName;
            name = System.IO.Path.GetFileNameWithoutExtension(fileName);

            var con = new System.Data.SQLite.SQLiteConnection();
            con.ConnectionString = "Data Source=" + fileName;
            con.Open();


            using (var tSQLiteCommand = con.CreateCommand())
            {
                tSQLiteCommand.CommandText = "select * from packets Limit(6)";
                using (var treader = tSQLiteCommand.ExecuteReader())
                {
                    int tTotal = treader.RecordsAffected;



                    while (treader.Read())
                    {

                        var OpcodeEnum = (Opcodes)treader.GetInt32(4);


                        if (OpcodeEnum == Opcodes.CMSG_AUTH_SESSION)
                        {
                            var id = treader.GetInt32(0);
                            var sessionid = treader.GetInt32(1);
                            var logstarted = treader.GetDateTime(2);
                            var direction = treader.GetInt32(3);
                            var blob = (byte[])treader.GetValue(5);

                            using (var qs = new PACKETPARSERMAX20.CORE.QuickStream())
                            {

                                qs.Load(blob);

                                clientBuild = qs.ReadUInt16();
                                var _unknown1 = qs.ReadUInt16();
                                var _unknown2 = qs.ReadUInt32();
                                accountName = qs.ReadString();
                                // var _clientSeed = qs.ReadUInt32();
                                break;
                            }
                        }
                    }

                    treader.Close();
                }


            }

            con.Close();

        }

        ~ReaderSniffitzSQLiteOLD()
        {
            Close();
        }

        public override void Load()
        {
            Load("");
        }

        public override void Load(string pCustomerQuery)
        {
            System.Data.SQLite.SQLiteCommand tSQLiteCommand = Con.CreateCommand();
            tSQLiteCommand.CommandText = string.Format("select id, timestamp, direction, opcode, data from packets where id >= {0} {1} Limit({2})", currentIndex, pCustomerQuery, maxProcessCount); ;
            reader = tSQLiteCommand.ExecuteReader();

            //packets (id integer primary key autoincrement, sess_id integer, timestamp datetime, direction integer, opcode integer, data blob)
        }

        public override int GetTotalByQuery(string pQuery)
        {
            int tTotal = 0;

            try
            {

                using (System.Data.SQLite.SQLiteCommand tSQLiteCommand = Con.CreateCommand())
                {
                    tSQLiteCommand.CommandText = string.Format("select count(*) from packets {0}", pQuery);
                    using (System.Data.SQLite.SQLiteDataReader tempreader = tSQLiteCommand.ExecuteReader())
                    {
                        tTotal = tempreader.RecordsAffected;
                        if (tempreader.Read())
                        {
                            tTotal = tempreader.GetInt32(0);
                        }
                        tempreader.Close();
                    }
                }
            }
            catch //(Exception exc)
            {

                try
                {

                    using (System.Data.SQLite.SQLiteCommand tSQLiteCommand = Con.CreateCommand())
                    {
                        tSQLiteCommand.CommandText = string.Format("select id from packets {0}", pQuery);
                        using (System.Data.SQLite.SQLiteDataReader tempreader = tSQLiteCommand.ExecuteReader())
                        {
                            while (tempreader.Read())
                            {
                                tTotal++;
                            }
                            tempreader.Close();
                        }
                    }
                }
                catch //(Exception exc2)
                {

                }
            }

            return tTotal;
        }

        public static bool IsValid(string pFile)
        {
            bool result = true;
            try
            {
                var test = new ReaderSniffitzSQLiteOLD(pFile);
                result = test.ValidateFields();
                test.Close();
                test = null;
            }
            catch (Exception ex)
            {
                result = false;
            }

            return result;
        }

        public bool ValidateFields()
        {
            System.Data.SQLite.SQLiteCommand tSQLiteCommand = Con.CreateCommand();
            tSQLiteCommand.CommandText = "select * from packets Limit(6)";
            reader = tSQLiteCommand.ExecuteReader();
            int tTotal = reader.RecordsAffected;



            while (reader.Read())
            {

                var OpcodeEnum = (Opcodes)reader.GetInt32(4);


                if (OpcodeEnum == Opcodes.CMSG_AUTH_SESSION)
                {
                    var id = reader.GetInt32(0);
                    var sessionid = reader.GetInt32(1);
                    var logstarted = reader.GetDateTime(2);
                    var direction = reader.GetInt32(3);
                    var blob = (byte[])reader.GetValue(5);

                    using (var qs = new PACKETPARSERMAX20.CORE.QuickStream())
                    {

                        qs.Load(blob);

                        clientBuild = qs.ReadUInt16();
                        var _unknown1 = qs.ReadUInt16();
                        var _unknown2 = qs.ReadUInt32();
                        accountName = qs.ReadString();
                        // var _clientSeed = qs.ReadUInt32();
                        break;
                    }
                }
            }


            return reader.FieldCount == 6;
        }


        private System.Data.SQLite.SQLiteConnection Con
        {
            get
            {
                if (con == null)
                    con = new System.Data.SQLite.SQLiteConnection();

                if (con.State == System.Data.ConnectionState.Executing)
                    con.Close();


                if (con.State != System.Data.ConnectionState.Open)
                {
                    con.ConnectionString = "Data Source=" + fileName;
                    con.Open();
                }

                if (con.State != System.Data.ConnectionState.Open)
                    throw new Exception(string.Format("failed to open connection {0}", con.ConnectionString));

                return con;
            }
        }

        private int GetTotal()
        {
            int tTotal = 0;

            try
            {

                using (System.Data.SQLite.SQLiteCommand tSQLiteCommand = Con.CreateCommand())
                {
                    tSQLiteCommand.CommandText = "select count(*) from packets";
                    using (System.Data.SQLite.SQLiteDataReader tempreader = tSQLiteCommand.ExecuteReader())
                    {
                        tTotal = tempreader.RecordsAffected;
                        if (tempreader.Read())
                        {
                            tTotal = tempreader.GetInt32(0);
                        }
                        tempreader.Close();
                    }
                }
            }
            catch //(Exception exc)
            {

                try
                {

                    using (System.Data.SQLite.SQLiteCommand tSQLiteCommand = Con.CreateCommand())
                    {
                        tSQLiteCommand.CommandText = "select id from packets";
                        using (System.Data.SQLite.SQLiteDataReader tempreader = tSQLiteCommand.ExecuteReader())
                        {
                            while (tempreader.Read())
                            {
                                tTotal++;
                            }
                            tempreader.Close();
                        }
                    }
                }
                catch //(Exception exc2)
                {

                }
            }

            return tTotal;

        }

        public override Packet GetNextPacket()
        {
            Packet tPacket = null;
            if (reader != null)
            {

                try
                {

                    if (reader.Read())
                    {
                        try
                        {
                            int id = reader.GetInt32(0);
                            DateTime datetime = reader.GetDateTime(1);
                            int direction = reader.GetInt32(2);
                            uint opcode = (uint)reader.GetInt32(3);
                            Object tBlob = reader.GetValue(4);

                            byte[] data = new byte[0];

                            if (!DBNull.Value.Equals(tBlob))
                            {
                                data = (byte[])tBlob;

                                //decompress
                                if (opcode == 502 || opcode == 763 || (ClientBuild < 9183 && opcode == 751))
                                {
                                    using (System.IO.MemoryStream ms = new System.IO.MemoryStream(data))
                                    {
                                        using (System.IO.BinaryReader br = new System.IO.BinaryReader(ms))
                                        {
                                            ComponentAce.Compression.Libs.zlib.ZStream tZStream = new ComponentAce.Compression.Libs.zlib.ZStream();
                                            byte[] tnew = new byte[data.Length - 4];
                                            System.Array.Copy(data, 4, tnew, 0, data.Length - 4);
                                            int tdecompsize = br.ReadInt32();
                                            byte[] tdecompdata = new byte[tdecompsize];
                                            tZStream.inflateInit();
                                            tZStream.avail_in = tnew.Length;
                                            tZStream.next_in = tnew;
                                            tZStream.avail_out = tdecompsize;
                                            tZStream.next_out = tdecompdata;
                                            int ret = tZStream.inflate(ComponentAce.Compression.Libs.zlib.zlibConst.Z_NO_FLUSH);
                                            int ret2 = tZStream.inflateEnd();

                                            data = tdecompdata;
                                        }
                                    }
                                }
                            }
                            tPacket = new Packet(id, datetime, (byte)direction, opcode, data, data.Length, ClientBuild);

                            currentIndex = id;

                        }
                        catch (Exception exc)
                        {
                            System.Console.WriteLine(string.Format("Log {0} at index {1} has Error: {2}", fileName, currentIndex + 1, exc.Message));
                            System.Diagnostics.Debug.WriteLine(string.Format("Log {0} at index {1} has Error: {2}", fileName, currentIndex + 1, exc.Message));
                        }
                    }
                }
                catch (Exception exc)
                {
                    System.Console.WriteLine(string.Format("Log {0} at index {1} has Error: {2}", fileName, currentIndex + 1, exc.Message));
                    System.Diagnostics.Debug.WriteLine(string.Format("Log {0} at index {1} has Error: {2}", fileName, currentIndex + 1, exc.Message));

                }
            }

            return tPacket;
        }

        public override int SkipPackets(int pCount)
        {

            if (reader != null)
            {

                try
                {
                    for (int i = 0; i < pCount; i++)
                    {
                        if (reader.Read())
                        {
                            try
                            {
                                int id = reader.GetInt32(0);

                                currentIndex = id;

                            }
                            catch (Exception exc)
                            {
                                System.Console.WriteLine(string.Format("Log {0} at index {1} has Error: {2}", fileName, currentIndex + 1, exc.Message));
                                System.Diagnostics.Debug.WriteLine(string.Format("Log {0} at index {1} has Error: {2}", fileName, currentIndex + 1, exc.Message));
                            }
                        }
                    }
                }
                catch (Exception exc)
                {
                    System.Console.WriteLine(string.Format("Log {0} at index {1} has Error: {2}", fileName, currentIndex + 1, exc.Message));
                    System.Diagnostics.Debug.WriteLine(string.Format("Log {0} at index {1} has Error: {2}", fileName, currentIndex + 1, exc.Message));

                }
            }

            return currentIndex;
        }

        public static void CopyStream(System.IO.Stream input, System.IO.Stream output)
        {
            byte[] buffer = new byte[2000];
            int len;
            while ((len = input.Read(buffer, 0, 2000)) > 0)
            {
                output.Write(buffer, 0, len);
            }
            output.Flush();
        }

        private byte[] decompress(byte[] inData)
        {
            byte[] tReturn = null;
            System.IO.MemoryStream outMemoryStream = new System.IO.MemoryStream();
            ComponentAce.Compression.Libs.zlib.ZOutputStream outZStream = new ComponentAce.Compression.Libs.zlib.ZOutputStream(outMemoryStream);
            System.IO.MemoryStream inMemoryStream = new System.IO.MemoryStream(inData);
            try
            {
                CopyStream(inMemoryStream, outZStream);
                tReturn = new byte[outMemoryStream.Length];
                outMemoryStream.Position = 0;
                int tok = outMemoryStream.Read(tReturn, 0, (int)outMemoryStream.Length);
            }
            finally
            {
                outZStream.Close();
                outMemoryStream.Close();
                inMemoryStream.Close();
            }

            return tReturn;

        }

        public override void Close()
        {
            if (reader != null)
            {
                if (con.State != System.Data.ConnectionState.Closed)
                    reader.Close();
                CurrentIndex = 0;
                total = -1;

            }
            if (con != null)
            {
                con.Close();
                con = null;
            }

            reader = null;
        }

        public override void Reset()
        {
            Close();
            Load();
        }

        public override string FileName
        {
            get { return fileName; }
        }
    }
}
